home *** CD-ROM | disk | FTP | other *** search
- //--------------------------------------------------------------------------
- // filename "VED04B.CPP"
- // VED v0.4 beta
- // Vector Editor
- // coded by Tumblin / Bodies In Motion
- //--------------------------------------------------------------------------
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <alloc.h>
- #include <math.h>
- #include <conio.h>
- #include <dos.h>
- #include <XLib_all.h>
- #include "ved04clr.h"
-
-
- typedef long Fixedpoint;
-
- #define Int2Fixed(a) (Fixedpoint)((Fixedpoint)(a) << 16)
- #define Fixed2Int(a) (int)((a) >> 16)
- #define Float2Fixed(a) ((Fixedpoint)((a) * 65536.0))
- #define Fixed2Float(a) ((a) / 65536.0)
-
-
- extern "C" {
- Fixedpoint FixedMul(Fixedpoint,Fixedpoint);
- Fixedpoint FixedDiv(Fixedpoint,Fixedpoint);
- };
-
- //--------------------------------------------------------------------
-
-
- int debug_mode=0; // 1=on, 0=off
-
- #define MaxDegrees 360
-
- #define WINDOW_TOP 0
- #define WINDOW_BOTTOM 239
- #define WINDOW_LEFT 0
- #define WINDOW_RIGHT 319
-
-
- int distance=256; // distance of object from screen
-
- // sin and cos lookup tables
- Fixedpoint cosine[MaxDegrees];
- Fixedpoint sine[MaxDegrees];
-
- int xangle=0;
- int yangle=0;
- int zangle=0;
-
- char filename[80];
-
- unsigned int NumOfFrames=0;
-
- float dotproduct;
-
- int LightSourceMode=0; // use default light source coordinates
-
- unsigned char oldpalette[768]; // palette before running VED
- unsigned char currentpalette[768]={0}; // temporary palette for fading
-
-
- //--------------------------------------------------------------------
-
-
- // structure for one vertex
- typedef struct
- {
- Fixedpoint ox; // vertex's original coordinates
- Fixedpoint oy;
- Fixedpoint oz;
- Fixedpoint wx; // vertex's working coordinates
- Fixedpoint wy;
- Fixedpoint wz;
- int sx; // vertex's screen coordinates
- int sy;
- int sz;
- } VertexTYPE;
-
-
- // structure for polygons
- typedef struct
- {
- int NumOfVertices; // number of vertices in polygon
- int Color; // calculated color of the polygon
- int ShadingColor; // original VED v0.3 beta color for polygon (1-7)
- int zmax,zmin; // minimum and maximum
- int xmax,xmin; // minimum and maximum
- int ymax,ymin; // minimum and maximum
- int zcenter; // polygon's center in the z dimention
- int xcenter; // polygon's center in the x dimention
- int ycenter; // polygon's center in the y dimention
- VertexTYPE **Vertex; // array of pointers to vertices
- Fixedpoint Normalox; // original x coordinate of polygon normal
- Fixedpoint Normaloy; // original y coordinate of polygon normal
- Fixedpoint Normaloz; // original z coordinate of polygon normal
- Fixedpoint Normalwx; // working copy x coordinate of polygon normal
- Fixedpoint Normalwy; // working copy y coordinate of polygon normal
- Fixedpoint Normalwz; // working copy z coordinate of polygon normal
- } PolygonTYPE;
-
-
- // structure for vertex information of clipped polygons
- typedef struct
- {
- int x,y,z; // screen coordinates for clipped polygon vertices
- int x1,y1,z1; // intermediate coordinates (same as above)
- } ClipTYPE;
-
-
- // structure for clipped polygons
- typedef struct
- {
- int NumOfVertices; // # of vertices in clipped polygon
- int Color; // color of clipped polygon
- ClipTYPE Vertex[50]; // holds the list of vertices in clipped polygon
- int xmin,xmax; // minimum and maximum x-coordinates of clipped polygon
- int ymin,ymax; // minimum and maximum y-coordinates of clipped polygon
- int zmin,zmax; // minimum and maximum z-coordinates of clipped polygon
- } ClippedPolygonTYPE;
-
-
- // structure for complete vector object
- typedef struct
- {
- int NumOfVertices; // how many vertices in entire object
- int NumOfPolygons; // how many polygons in entire object
- PolygonTYPE * Polygon; // list of polygons in object
- VertexTYPE * Vertex; // list of vertices
- } ObjectTYPE;
-
-
- // structure for polygon list
- typedef struct
- {
- int NumOfPolygons; // number of polygons in polygon list
- PolygonTYPE Polygon[100]; // list of polygons
- } PolygonListTYPE;
-
-
-
- // structure for light source for use in shading
- typedef struct
- {
- Fixedpoint x;
- Fixedpoint y;
- Fixedpoint z;
- } LightSourceTYPE;
-
- // structure for erasing box
- typedef struct
- {
- int top;
- int bottom;
- int left;
- int right;
- } EraseBoxTYPE;
-
-
- //----------------------------------------------------------------------
-
-
- // origional polygon vector object
- ObjectTYPE Object;
-
- // polygon list
- PolygonListTYPE PolygonList;
-
- // clipped polygon array
- ClippedPolygonTYPE ClipArray;
-
- // light source
- LightSourceTYPE LightSource;
-
- // Erasing box
- EraseBoxTYPE EraseBoxNew,EraseBoxOld,EraseBoxVeryOld;
-
- //---------------------------------------------------------------
-
-
- void Create_lookup_tables(void)
- {
- int i;
- for(i=0; i<MaxDegrees; i++)
- {
- cosine[i]=Float2Fixed(cos((float)i*360/MaxDegrees * 3.14159265 / 180.0));
- sine[i] =Float2Fixed(sin((float)i*360/MaxDegrees * 3.14159265 / 180.0));
- }
- }
-
-
- //---------------------------------------------------------------
-
-
- // function prototypes
- void Rotate_vector_object(void);
- void Create_lookup_tables(void);
- int main(int argc,char *argv[]);
- int LoadObject(char *);
- int getnumber(FILE *f);
- char nextchar(FILE *f);
- void RotateOnX(void);
- void RotateOnY(void);
- void RotateOnZ(void);
- void RotateOnAll(void);
- void SelectDistance(void);
- void MakePolygonList(void);
- int Backface(PolygonTYPE p);
- void ZSort();
- void ShowObject(void);
- void DrawPolygonList(void);
- void DrawDebugDots(void);
- void CalculateColor(void);
- void CalculateNormals(void);
- void Rotate_Normals(void);
- void SetupLightSourceManually(void);
- void SetupLightSourceDefault(void);
- void InitializeEraseBox(void);
- void ZClip(PolygonTYPE *polygon, ClippedPolygonTYPE *clip);
- void XYClip(ClippedPolygonTYPE *clip);
- void WaitVerticalRetrace(void);
- void FadeInPalette(unsigned char *,int);
- void FadeOutPalette(int);
- void GetPalette(unsigned char *);
- void SetPalette(unsigned char *);
- void FadeInOne64th(unsigned char *,unsigned char *);
- void FadeOutOne64th(unsigned char *);
-
-
-
- //--------------------------------------------------------------------
-
-
- void RotateOnAll(void)
- {
- xangle=0;
- yangle=0;
- zangle=0;
-
- SetPalette(currentpalette);
- x_set_mode(X_MODE_320x240,320);
- x_set_doublebuffer(240);
- FadeInPalette(vedpalette,1);
-
- // rotate around all three axis 3 times
- do
- {
- if((xangle+=3) >= MaxDegrees)
- xangle=0;
- if((yangle+=2) >= MaxDegrees)
- yangle=0;
- if((zangle+=3) >= MaxDegrees)
- zangle=0;
- ShowObject();
- x_page_flip(0,0);
- if(kbhit())
- break;
- } while(!kbhit());
- getch();
- FadeOutPalette(1);
- x_text_mode();
- }
-
-
- //-----------------------------------------------------------------------
-
-
- void RotateOnX(void)
- {
- xangle=270;
- yangle=180;
- zangle=180;
-
- SetPalette(currentpalette);
- x_set_mode(X_MODE_320x240,320);
- x_set_doublebuffer(240);
- FadeInPalette(vedpalette,1);
-
- // rotate around all three axis 3 times
- do
- {
- if((xangle+=1) >= MaxDegrees)
- xangle=0;
- ShowObject();
- x_page_flip(0,0);
- if(kbhit())
- break;
- } while(!kbhit());
- getch();
- FadeOutPalette(1);
- x_text_mode();
- }
-
-
- //-----------------------------------------------------------------------
-
-
- void RotateOnY(void)
- {
- xangle=90;
- yangle=0;
- zangle=0;
-
- SetPalette(currentpalette);
- x_set_mode(X_MODE_320x240,320);
- x_set_doublebuffer(240);
- FadeInPalette(vedpalette,1);
-
- // rotate around all three axis 3 times
- do
- {
- if((yangle+=1) >= MaxDegrees)
- yangle=0;
- ShowObject();
- x_page_flip(0,0);
- if(kbhit())
- break;
- } while(!kbhit());
- getch();
- FadeOutPalette(1);
- x_text_mode();
- }
-
-
- //-----------------------------------------------------------------------
-
-
- void RotateOnZ(void)
- {
- xangle=270;
- yangle=180;
- zangle=180;
-
- SetPalette(currentpalette);
- x_set_mode(X_MODE_320x240,320);
- x_set_doublebuffer(240);
- FadeInPalette(vedpalette,1);
-
- // rotate around all three axis 3 times
- do
- {
- if((zangle+=1) >= MaxDegrees)
- zangle=0;
- ShowObject();
- x_page_flip(0,0);
- if(kbhit())
- break;
- } while(!kbhit());
- getch();
- FadeOutPalette(1);
- x_text_mode();
- }
-
-
- //----------------------------------------------------------------------
-
-
- void SelectDistance(void)
- {
- SetPalette(currentpalette);
- x_text_mode();
- FadeInPalette(vedpalette,1);
- printf("Please enter the distance away from the screen : ");
- scanf("%li",&distance);
- FadeOutPalette(1);
- x_text_mode();
- }
-
-
- //----------------------------------------------------------------------
-
-
- void Rotate_vector_object(void)
- {
- int i;
- long tempx,tempy,tempz;
-
- Fixedpoint nx,ny,nz,cosxangle,sinxangle,cosyangle,sinyangle,coszangle,sinzangle;
-
- // get the sine and cosine angles to save time from table lookup
- sinxangle=sine[xangle];
- cosxangle=cosine[xangle];
- sinyangle=sine[yangle];
- cosyangle=cosine[yangle];
- sinzangle=sine[zangle];
- coszangle=cosine[zangle];
-
- // first we have to do all the rotations
- for(i=0;i<Object.NumOfVertices;i++)
- {
- // rotate around the x-axis
- Object.Vertex[i].wz=FixedMul(Object.Vertex[i].oy,cosxangle) - FixedMul(Object.Vertex[i].oz,sinxangle);
- Object.Vertex[i].wy=FixedMul(Object.Vertex[i].oy,sinxangle) + FixedMul(Object.Vertex[i].oz,cosxangle);
- Object.Vertex[i].wx=Object.Vertex[i].ox;
-
- // rotate around the y-axis
- nx=FixedMul(-Object.Vertex[i].wx,cosyangle) + FixedMul(Object.Vertex[i].wz,sinyangle);
- nz=FixedMul(Object.Vertex[i].wx,sinyangle) + FixedMul(Object.Vertex[i].wz,cosyangle);
- Object.Vertex[i].wx=nx;
- Object.Vertex[i].wz=nz;
-
- // rotate around the z-axis
- nx=FixedMul(Object.Vertex[i].wx,coszangle) - FixedMul(Object.Vertex[i].wy,sinzangle);
- ny=FixedMul(Object.Vertex[i].wx,sinzangle) + FixedMul(Object.Vertex[i].wy,coszangle);
- Object.Vertex[i].wx=nx;
- Object.Vertex[i].wy=ny;
-
-
- // project the 3-D coordinates to screen coordinates
- Object.Vertex[i].sx=Fixed2Int(FixedMul(FixedDiv(Object.Vertex[i].wx,Object.Vertex[i].wz-Int2Fixed(distance)),Int2Fixed(256))) + (long)160;
- Object.Vertex[i].sy=Fixed2Int(FixedMul(FixedDiv(Object.Vertex[i].wy,Object.Vertex[i].wz-Int2Fixed(distance)),Int2Fixed(256))) + (long)120;
- Object.Vertex[i].sz=Fixed2Int(Object.Vertex[i].wz-Int2Fixed(distance));
- }
- }
-
-
- //---------------------------------------------------------------
-
-
- int main(int argc,char *argv[])
- {
- if(argc<=1)
- {
- printf("┌─────────────┐\n");
- printf("│VED v0.4 beta│\n");
- printf("└─────────────┘\n");
- printf("syntax: VED04B filename.V04\n\n");
- exit(1);
- }
-
- if(LoadObject(argv[1])!=0)
- {
- printf("Could not find that file. Check to see if you gave the correct filename.\n");
- exit(1);
- }
-
- char menu_option;
- int time_to_quit=0;
-
- // initialize very old erase box
- EraseBoxVeryOld.top=WINDOW_TOP;
- EraseBoxVeryOld.bottom=WINDOW_BOTTOM;
- EraseBoxVeryOld.left=WINDOW_LEFT;
- EraseBoxVeryOld.right=WINDOW_RIGHT;
-
- // initialize old erase box
- EraseBoxOld.top=WINDOW_TOP;
- EraseBoxOld.bottom=WINDOW_BOTTOM;
- EraseBoxOld.left=WINDOW_LEFT;
- EraseBoxOld.right=WINDOW_RIGHT;
-
- Create_lookup_tables();
- CalculateNormals();
- SetupLightSourceDefault();
- InitializeEraseBox();
- x_text_init();
-
- GetPalette(oldpalette);
- FadeOutPalette(1);
- x_text_mode();
-
- do // display the main menu
- {
- SetPalette(currentpalette);
- printf(" ┌─────────────┐\n");
- printf(" │VED v0.4 beta│\n");
- printf(" └─────────────┘\n\n");
- printf(" coded by Tumblin / Bodies In Motion\n\n\n");
- printf(" Distance = %i\n",distance);
- printf(" Light source = (%f,%f,%f)\n\n",Fixed2Float(LightSource.x),Fixed2Float(LightSource.y),Fixed2Float(LightSource.z));
- printf(" ┌───────────── MAIN MENU ────────────┐\n");
- printf(" │ [X] Rotate object on X-axis │\n");
- printf(" │ [Y] Rotate object on Y-axis │\n");
- printf(" │ [Z] Rotate object on Z-axis │\n");
- printf(" │ [A] Rotate object on all three axis│\n");
- printf(" │ [D] Select distance from viewer │\n");
- printf(" │ [L] Select new light source │\n");
- printf(" │ [Q] Quit │\n");
- printf(" └────────────────────────────────────┘\n");
- printf(" Make your selection : ");
- FadeInPalette(vedpalette,1);
- menu_option=getche();
-
- // reset the number of frames shown
- NumOfFrames=0;
-
- // evaluate user's selection
- if(menu_option=='x' || menu_option=='X')
- RotateOnX();
- if(menu_option=='y' || menu_option=='Y')
- RotateOnY();
- if(menu_option=='z' || menu_option=='Z')
- RotateOnZ();
- if(menu_option=='a' || menu_option=='A')
- RotateOnAll();
- if(menu_option=='d' || menu_option=='D')
- SelectDistance();
- if(menu_option=='q' || menu_option=='Q')
- time_to_quit=1;
- if(menu_option=='l' || menu_option=='L')
- SetupLightSourceManually();
-
- } while(time_to_quit != 1);
-
- free(&Object);
- free(&PolygonList);
- FadeOutPalette(1);
- x_text_mode();
- printf("This has been a Bodies In Motion production.\n\n");
- FadeInPalette(oldpalette,1);
- return(0);
- }
-
-
- //--------------------------------------------------------------------------
-
-
- int LoadObject(char *filename)
- {
- FILE *f;
- int num,vertnum,polynum;
-
- ObjectTYPE *object=&Object;
-
- f=fopen(filename,"r");
- if(f==NULL)
- {
- printf("Could not find that file. Check to see if you gave the correct filename.\n");
- exit(1);
- }
- // first get the number of vertices in the object
- object->NumOfVertices=getnumber(f);
- // allocate memory for vertex array
- object->Vertex=new VertexTYPE[object->NumOfVertices];
- // load vertices into vertex array
- for(vertnum=0; vertnum < object->NumOfVertices; vertnum++)
- {
- // assign pointer to current vertex
- VertexTYPE *curvert=&object->Vertex[vertnum];
- // get the original local coordinates
- curvert->ox=Int2Fixed(getnumber(f));
- curvert->wx=curvert->ox;
- curvert->oy=Int2Fixed(getnumber(f));
- curvert->wy=curvert->oy;
- curvert->oz=Int2Fixed(getnumber(f));
- curvert->wz=curvert->oz;
- }
- // get the number of polygons in the object
- object->NumOfPolygons=getnumber(f);
- // assign memory for polygon array
- object->Polygon=new PolygonTYPE[object->NumOfPolygons];
- // load polygons into polygon array
- for(polynum=0; polynum < object->NumOfPolygons; polynum++)
- {
- // assign pointer to current polygon
- PolygonTYPE *curpoly=&object->Polygon[polynum];
- // get number of vertices in current polygon
- curpoly->NumOfVertices=getnumber(f);
- // assign memory for vertex array
- curpoly->Vertex=new VertexTYPE *[curpoly->NumOfVertices];
- // create array of pointers to vertices
- for(vertnum=0;vertnum<curpoly->NumOfVertices;vertnum++)
- {
- // allocate memory for pointer and point it at vertex in vertex array
- curpoly->Vertex[vertnum]=&object->Vertex[getnumber(f)];
- }
- // get color of current polygon
- curpoly->ShadingColor=getnumber(f);
- }
- fclose(f);
- return(0);
- }
-
- int getnumber(FILE *f)
- {
- int num;
- char ch;
- int sign=1;
-
- num=0;
- if((ch=nextchar(f))=='-')
- {
- sign=-1;
- ch=nextchar(f);
- }
- while(isdigit(ch))
- {
- num=num*10+ch-'0';
- ch=nextchar(f);
- }
- return(num*sign);
- }
-
- char nextchar(FILE *f)
- {
- char ch;
-
- while(!feof(f))
- {
- while(isspace(ch=fgetc(f)));
- if (ch=='*')
- while((ch=fgetc(f))!='\n');
- else return(ch);
- }
- return(0);
- }
-
-
- //--------------------------------------------------------------------------
-
-
- void MakePolygonList(void)
- {
- // create a list of all polygons potentially visible on the display,
- // removing backfaces and determine the minimum and maximum z coordinates
-
- int count=0; // determine # of polygons in list
-
- // loop through all polygons in object
- for(int polynum=0; polynum < Object.NumOfPolygons; polynum++)
- {
- // create a pointer to current polygon
- PolygonTYPE *polyptr=&Object.Polygon[polynum];
-
- // if polygon isn't a backface, consider it for list
- if(!Backface(*polyptr))
- {
- int pzmax=-32767; // initialize min and max to
- int pzmin=32767; // highest & lowest possible values
- int pxmax=-32767; // initialize min and max to
- int pxmin=32767; // highest & lowest possible values
- int pymax=-32767; // initialize min and max to
- int pymin=32767; // highest & lowest possible values
-
- // loop through all vertices in polygon to find ones with higher
- // and lower coordinates than current min & max
- for(int v=0; v < polyptr->NumOfVertices; v++)
- {
- // do the z-axis
- if(polyptr->Vertex[v]->sz > pzmax)
- {
- pzmax=polyptr->Vertex[v]->sz;
- }
- if(polyptr->Vertex[v]->sz < pzmin)
- {
- pzmin=polyptr->Vertex[v]->sz;
- }
-
- // do the x-axis
- if(polyptr->Vertex[v]->sx > pxmax)
- {
- pxmax=polyptr->Vertex[v]->sx;
- }
- if(polyptr->Vertex[v]->sx < pxmin)
- {
- pxmin=polyptr->Vertex[v]->sx;
- }
-
- // do the y-axis
- if(polyptr->Vertex[v]->sy > pymax)
- {
- pymax=polyptr->Vertex[v]->sy;
- }
- if(polyptr->Vertex[v]->sy < pymin)
- {
- pymin=polyptr->Vertex[v]->sy;
- }
- }
-
- // put min and max in polygon descriptor
- polyptr->zmin=pzmin;
- polyptr->zmax=pzmax;
- polyptr->xmin=pxmin;
- polyptr->xmax=pxmax;
- polyptr->ymin=pymin;
- polyptr->ymax=pymax;
-
- // calculate center of polygon
- polyptr->zcenter=(pzmax+pzmin)>>1;
- polyptr->xcenter=(pxmax+pxmin)>>1;
- polyptr->ycenter=(pymax+pymin)>>1;
-
- // if polygon is in front of view plane, add it to the list
- if(pzmax < 0)
- {
- PolygonList.Polygon[count++]=*polyptr;
- }
- }
- }
- PolygonList.NumOfPolygons=count;
- }
-
-
- //-------------------------------------------------------------------------
-
-
- int Backface(PolygonTYPE p)
- {
- // returns 0 if polygon is visible, -1 if not
- // the polygon must be part of a convex polyhedron
-
- VertexTYPE *v0,*v1,*v2; // pointers to three vertices
-
- // point to vertices
- v0=p.Vertex[0];
- v1=p.Vertex[1];
- v2=p.Vertex[2];
-
- int z= (v1->sx - v0->sx) * (v2->sy - v0->sy)
- -(v1->sy - v0->sy) * (v2->sx - v0->sx);
-
- return(z<0);
- }
-
-
- //--------------------------------------------------------------------------
-
-
- void ZSort(void)
- {
- // sort the polygon list into reverse order by z coordinates
-
- int swapflag=-1; // force initial pass through list
- while(swapflag) // loop until no swaps performed
- {
- swapflag=0;
-
- // loop through polygon list
- for(int i=0; i < (PolygonList.NumOfPolygons-1);i++)
- {
- // are polygons in order?
- if(PolygonList.Polygon[i].zcenter > PolygonList.Polygon[i+1].zcenter)
- {
- // if so, swap them
- PolygonTYPE temp=PolygonList.Polygon[i];
- PolygonList.Polygon[i]=PolygonList.Polygon[i+1];
- PolygonList.Polygon[i+1]=temp;
- swapflag=-1; // indicate that swap was performed
- }
- }
- }
- }
-
-
- //-------------------------------------------------------------------------
-
-
- void DrawPolygonList()
- {
- int i,j;
-
- // erase the previous frame
- x_rect_fill(EraseBoxVeryOld.left,EraseBoxVeryOld.top,EraseBoxVeryOld.right+1,EraseBoxVeryOld.bottom+1,HiddenPageOffs,0);
-
- // loop through polygon list and draw each polygon
- for(i=0; i<PolygonList.NumOfPolygons;i++)
- {
- ZClip(&PolygonList.Polygon[i],&ClipArray);
- if(ClipArray.NumOfVertices > 0)
- {
- // clip against sides of viewport
- XYClip(&ClipArray);
- // check to make sure polygon wan't clipped out of existence
- if(ClipArray.NumOfVertices > 0)
- {
- // draw polygon
-
- // loop through all vertices in polygon and draw triangular pieces
- for(j=0; j < ClipArray.NumOfVertices-2;j++)
- {
- x_triangle(ClipArray.Vertex[0].x,
- ClipArray.Vertex[0].y,
- ClipArray.Vertex[j+1].x,
- ClipArray.Vertex[j+1].y,
- ClipArray.Vertex[j+2].x,
- ClipArray.Vertex[j+2].y,
- ClipArray.Color,
- HiddenPageOffs);
- }
- }
- }
- }
-
- InitializeEraseBox();
-
- // figure out the bounding box for erasing the object next frame
- for(i=0; i<Object.NumOfVertices; i++)
- {
- if(Object.Vertex[i].sy < EraseBoxNew.top)
- EraseBoxNew.top=Object.Vertex[i].sy;
- if(Object.Vertex[i].sy > EraseBoxNew.bottom)
- EraseBoxNew.bottom=Object.Vertex[i].sy;
- if(Object.Vertex[i].sx < EraseBoxNew.left)
- EraseBoxNew.left=Object.Vertex[i].sx;
- if(Object.Vertex[i].sx > EraseBoxNew.right)
- EraseBoxNew.right=Object.Vertex[i].sx;
- }
-
- // increase the right & bottom of the bounding box by one pixel
- // (something with the XLIB code that I don't understand :-)
- EraseBoxNew.right++;
- EraseBoxNew.bottom++;
-
- // clip the bounding box to screen limits
- if(EraseBoxNew.top < WINDOW_TOP)
- EraseBoxNew.top=WINDOW_TOP;
- if(EraseBoxNew.bottom > WINDOW_BOTTOM)
- EraseBoxNew.bottom=WINDOW_BOTTOM;
- if(EraseBoxNew.left < WINDOW_LEFT)
- EraseBoxNew.left=WINDOW_LEFT;
- if(EraseBoxNew.right > WINDOW_RIGHT)
- EraseBoxNew.right=WINDOW_RIGHT;
-
- // make the very old bounding box = the old bounding box
- EraseBoxVeryOld.top=EraseBoxOld.top;
- EraseBoxVeryOld.bottom=EraseBoxOld.bottom;
- EraseBoxVeryOld.left=EraseBoxOld.left;
- EraseBoxVeryOld.right=EraseBoxOld.right;
-
- // make the old bounding box = the new bounding box
- EraseBoxOld.top=EraseBoxNew.top;
- EraseBoxOld.bottom=EraseBoxNew.bottom;
- EraseBoxOld.left=EraseBoxNew.left;
- EraseBoxOld.right=EraseBoxNew.right;
-
- }
-
-
- //--------------------------------------------------------------
-
-
- void DrawDebugDots(void)
- {
- int i,j;
-
- // loop through all vertices in object
- for(i=0;i < Object.NumOfVertices; i++)
- {
- x_put_pix(Object.Vertex[i].sx,Object.Vertex[i].sy,HiddenPageOffs,15);
- x_printf(Object.Vertex[i].sx,Object.Vertex[i].sy,HiddenPageOffs,4,"%i",i);
- }
- }
-
- //--------------------------------------------------------------------------
-
-
- void CalculateNormals(void)
- {
- double x1,x2,x3,y1,y2,y3,z1,z2,z3,xlen,ylen,zlen,length;
-
- for(int i=0;i < Object.NumOfPolygons; i++)
- {
- x1=Fixed2Float(Object.Polygon[i].Vertex[0]->ox);
- x2=Fixed2Float(Object.Polygon[i].Vertex[1]->ox);
- x3=Fixed2Float(Object.Polygon[i].Vertex[2]->ox);
- y1=Fixed2Float(Object.Polygon[i].Vertex[0]->oy);
- y2=Fixed2Float(Object.Polygon[i].Vertex[1]->oy);
- y3=Fixed2Float(Object.Polygon[i].Vertex[2]->oy);
- z1=Fixed2Float(Object.Polygon[i].Vertex[0]->oz);
- z2=Fixed2Float(Object.Polygon[i].Vertex[1]->oz);
- z3=Fixed2Float(Object.Polygon[i].Vertex[2]->oz);
-
- // calculate perpendicular via the cross product of 1st vertex & normal
- xlen = Object.Polygon[i].Normalox = (y1-y2)*(z1-z3) - (z1-z2)*(y1-y3);
- ylen = Object.Polygon[i].Normaloy = (z1-z2)*(x1-x3) - (x1-x2)*(z1-z3);
- zlen = Object.Polygon[i].Normaloz = (x1-x2)*(y1-y3) - (y1-y2)*(x1-x3);
-
- // calculate the length of the normal
- length = sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
-
- // scale it to a unit normal
- Object.Polygon[i].Normalox = Float2Fixed(xlen / length);
- Object.Polygon[i].Normaloy = Float2Fixed(ylen / length);
- Object.Polygon[i].Normaloz = Float2Fixed(zlen / length);
- }
- }
-
-
- //--------------------------------------------------------------------------
-
-
- void CalculateColor(void)
- {
- int color;
-
- for(int i=0; i < Object.NumOfPolygons; i++)
- {
- dotproduct=FixedMul(Object.Polygon[i].Normalwx , LightSource.x) +
- FixedMul(Object.Polygon[i].Normalwy , LightSource.y) +
- FixedMul(Object.Polygon[i].Normalwz , LightSource.z);
-
- Object.Polygon[i].Color=Fixed2Int(FixedMul(dotproduct,Int2Fixed(16))) + Object.Polygon[i].ShadingColor*32;
-
- if(dotproduct>=Int2Fixed(0))
- Object.Polygon[i].Color=Fixed2Int(FixedMul(dotproduct,Int2Fixed(16))) + Object.Polygon[i].ShadingColor*32;
-
- }
- }
-
-
- //----------------------------------------------------------------------
-
-
- void Rotate_Normals(void)
- {
- int i;
- Fixedpoint nx,ny,nz,cosxangle,sinxangle,cosyangle,sinyangle,coszangle,sinzangle;
-
- // get the sine and cosine angles to save time from table lookup
- sinxangle=sine[xangle];
- cosxangle=cosine[xangle];
- sinyangle=sine[yangle];
- cosyangle=cosine[yangle];
- sinzangle=sine[zangle];
- coszangle=cosine[zangle];
-
- for(i=0;i<Object.NumOfPolygons;i++)
- {
- // rotate around the x-axis
- nz=FixedMul(Object.Polygon[i].Normaloy , cosxangle) - FixedMul(Object.Polygon[i].Normaloz , sinxangle);
- ny=FixedMul(Object.Polygon[i].Normaloy , sinxangle) + FixedMul(Object.Polygon[i].Normaloz , cosxangle);
- Object.Polygon[i].Normalwx=Object.Polygon[i].Normalox;;
- Object.Polygon[i].Normalwy=ny;
- Object.Polygon[i].Normalwz=nz;
-
- // rotate around the y-axis
- nx=FixedMul(-Object.Polygon[i].Normalwx , cosyangle) + FixedMul(Object.Polygon[i].Normalwz , sinyangle);
- nz=FixedMul(Object.Polygon[i].Normalwx , sinyangle) + FixedMul(Object.Polygon[i].Normalwz , cosyangle);
- Object.Polygon[i].Normalwx=nx;
- Object.Polygon[i].Normalwz=nz;
-
- // rotate around the z-axis
- nx=FixedMul(Object.Polygon[i].Normalwx , coszangle) - FixedMul(Object.Polygon[i].Normalwy , sinzangle);
- ny=FixedMul(Object.Polygon[i].Normalwx , sinzangle) + FixedMul(Object.Polygon[i].Normalwy , coszangle);
- Object.Polygon[i].Normalwx=-nx;
- Object.Polygon[i].Normalwy=-ny;
- Object.Polygon[i].Normalwz=-nz;
- }
- }
-
-
- //--------------------------------------------------------------------------
-
-
- void SetupLightSourceManually(void)
- {
- double xlen,ylen,zlen,length;
-
- x_text_mode();
- SetPalette(currentpalette);
- printf("Setting Light Source for shading\n");
- printf("Please enter values in the range of (+/-) 10, but not 0\n");
- printf("( the default is 10,10,10 ).\n\n");
- printf("Enter the light source's X coordinate : ");
- FadeInPalette(vedpalette,1);
- scanf("%lf",&xlen);
- printf("Enter the light source's Y coordinate : ");
- scanf("%lf",&ylen);
- printf("Enter the light source's Z coordinate : ");
- scanf("%lf",&zlen);
-
- // calculate the length of the vector (light source to 0,0,0)
- length = sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
-
- // scale it to a unit vector
- LightSource.x = Float2Fixed(-xlen/length);
- LightSource.y = Float2Fixed(ylen/length);
- LightSource.z = Float2Fixed(zlen/length);
- FadeOutPalette(1);
- x_text_mode();
- }
-
-
- //--------------------------------------------------------------------------
-
-
- void SetupLightSourceDefault(void)
- {
- double xlen,ylen,zlen,length;
-
- // assign the delault light source position
- xlen=10;
- ylen=10;
- zlen=10;
-
- // calculate the length of the vector (light source to 0,0,0)
- length = sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
-
- // scale it to a unit vector
- LightSource.x = Float2Fixed(-xlen/length);
- LightSource.y = Float2Fixed(ylen/length);
- LightSource.z = Float2Fixed(zlen/length);
- }
-
-
- //--------------------------------------------------------------------------
-
-
- void InitializeEraseBox(void)
- {
- // make the boundaries artificially extreme
- EraseBoxNew.top=WINDOW_BOTTOM;
- EraseBoxNew.bottom=WINDOW_TOP;
- EraseBoxNew.left=WINDOW_RIGHT;
- EraseBoxNew.right=WINDOW_LEFT;
- }
-
-
- //--------------------------------------------------------------------------
-
-
- void ZClip(PolygonTYPE *polygon, ClippedPolygonTYPE *clip)
- {
- // clip the polygon to the edges of the 3-d display area
-
- // create a pointer to the vertices of the clipped polygon structure
- ClipTYPE * pcv=clip->Vertex;
-
- // get info from polygon structure and put it into clipped
- // polygon structure
- clip->Color = polygon->Color;
- clip->xmin = polygon->xmin;
- clip->xmax = polygon->xmax;
- clip->ymin = polygon->ymin;
- clip->ymax = polygon->ymax;
- clip->zmin = polygon->zmin;
- clip->zmax = polygon->zmax;
-
- // clip the polygon against the front of the view volume
- int cp = 0; // point to current vertex of clipped polygon
- int zmin = -2; // set minimum z coordinate
-
- // initialize pointer to last vertex
- int v1=polygon->NumOfVertices - 1;
-
- // loop through all edges of the polygon
- for(int v2=0; v2 < polygon->NumOfVertices; v2++)
- {
- VertexTYPE *pv1 = polygon->Vertex[v1];
- VertexTYPE *pv2 = polygon->Vertex[v2];
-
- // categorize the edges by type
- if((pv1->sz <= zmin) && (pv2->sz <= zmin))
- {
- // edge entirely inside front
- pcv[cp].x = pv2->sx;
- pcv[cp].y = pv2->sy;
- pcv[cp++].z = pv2->sz;
- }
-
- if((pv1->sz <= zmin) && (pv2->sz > zmin))
- {
- // edge leaving view volume
- float t = (float)(zmin - pv1->sz)/(float)(pv2->sz - pv1->sz);
- pcv[cp].x = pv1->sx + (pv2->sx - pv1->sx) * t;
- pcv[cp].y = pv1->sy + (pv2->sy - pv1->sy) * t;
- pcv[cp++].z=zmin;
- }
- if((pv1->sz > zmin) && (pv2->sz <= zmin))
- {
- // edge is entering view volume
- float t = (float)(zmin - pv1->sz)/(float)(pv2->sz - pv1->sz);
- pcv[cp].x = pv1->sx + (pv2->sx - pv1->sx) * t;
- pcv[cp].y = pv1->sy + (pv2->sy - pv1->sy) * t;
- pcv[cp++].z = zmin;
- pcv[cp].x = pv2->sx;
- pcv[cp].y = pv2->sy;
- pcv[cp++].z = pv2->sz;
- }
- v1=v2; // advance to the next vertex
- }
- // update number of vertices in clipped polygon structure
- clip->NumOfVertices = cp;
- }
-
-
- //--------------------------------------------------------------------------
-
-
- void XYClip(ClippedPolygonTYPE *clip)
- {
- // clip polygon against sides of 3-d display area
-
- int temp; // miscellaneous temporary storage
- ClipTYPE *pcv = clip->Vertex;
-
- /////////////////////////////////////////////
- // clip polygon against left edge of display
- int cp = 0;
-
- // initialize pointer to last vertex
-
- int v1=clip->NumOfVertices - 1;
- for(int v2=0; v2 < clip->NumOfVertices; v2++)
- {
- // categorize edges by type
- if((pcv[v1].x >= WINDOW_LEFT) && (pcv[v2].x >= WINDOW_LEFT))
- {
- // edge isn't off left side of display
- pcv[cp].x1 = pcv[v2].x;
- pcv[cp++].y1 = pcv[v2].y;
- }
-
- if((pcv[v1].x >= WINDOW_LEFT) && (pcv[v2].x < WINDOW_LEFT))
- {
- // edge is leaving display
- float m = (float)(pcv[v2].y - pcv[v1].y)/(float)(pcv[v2].x - pcv[v1].x);
- pcv[cp].x1 = WINDOW_LEFT;
- pcv[cp++].y1 = pcv[v1].y + m * (WINDOW_LEFT - pcv[v1].x);
- }
- if((pcv[v1].x < WINDOW_LEFT) && (pcv[v2].x >= WINDOW_LEFT))
- {
- // edge is entering display
- float m = (float)(pcv[v2].y - pcv[v1].y)/(float)(pcv[v2].x - pcv[v1].x);
- pcv[cp].x1 = WINDOW_LEFT;
- pcv[cp++].y1 = pcv[v1].y + m * (WINDOW_LEFT - pcv[v1].x);
- pcv[cp].x1 = pcv[v2].x;
- pcv[cp++].y1 = pcv[v2].y;
- }
- v1=v2;
- }
- clip->NumOfVertices = cp;
-
- /////////////////////////////////////////////////////////
- // clip polygon against right edge of display
- cp = 0;
-
- // make pointer to last vertex
- v1=clip->NumOfVertices - 1;
- for(v2=0; v2 < clip->NumOfVertices; v2++)
- {
- // categorize edges by type
- if((pcv[v1].x1 <= WINDOW_RIGHT) && (pcv[v2].x1 <= WINDOW_RIGHT))
- {
- // edge isn't off right side of display
- pcv[cp].x = pcv[v2].x1;
- pcv[cp++].y = pcv[v2].y1;
- }
-
- if((pcv[v1].x1 <= WINDOW_RIGHT) && (pcv[v2].x1 > WINDOW_RIGHT))
- {
- // edge is leaving display
- float m = (float)(pcv[v2].y1 - pcv[v1].y1)/(float)(pcv[v2].x1 - pcv[v1].x1);
- pcv[cp].x = WINDOW_RIGHT;
- pcv[cp++].y = pcv[v1].y1 + m * (WINDOW_RIGHT - pcv[v1].x1);
- }
- if((pcv[v1].x1 > WINDOW_RIGHT) && (pcv[v2].x1 <= WINDOW_RIGHT))
- {
- // edge is entering display
- float m = (float)(pcv[v2].y1 - pcv[v1].y1)/(float)(pcv[v2].x1 - pcv[v1].x1);
- pcv[cp].x = WINDOW_RIGHT;
- pcv[cp++].y = pcv[v1].y1 + m * (WINDOW_RIGHT - pcv[v1].x1);
- pcv[cp].x = pcv[v2].x1;
- pcv[cp++].y = pcv[v2].y1;
- }
- v1 = v2;
- }
- clip->NumOfVertices = cp;
-
- ///////////////////////////////////////////////////////////////
- // clip polygon against upper edge of display
- cp = 0;
-
- // make pointer to last vertex
- v1 = clip->NumOfVertices - 1;
- for(v2=0; v2 < clip->NumOfVertices; v2++)
- {
- // categorize edges by type
- if((pcv[v1].y >= WINDOW_TOP) && (pcv[v2].y >= WINDOW_TOP))
- {
- // edge is not off top of display
- pcv[cp].x1 = pcv[v2].x;
- pcv[cp++].y1 = pcv[v2].y;
- }
-
- if((pcv[v1].y >= WINDOW_TOP) && (pcv[v2].y < WINDOW_TOP))
- {
- // edge is leaving display
- if((temp=pcv[v2].x - pcv[v1].x) != 0)
- {
- float m = (float)(pcv[v2].y - pcv[v1].y)/(float)temp;
- pcv[cp].x1 = pcv[v1].x + (WINDOW_TOP - pcv[v1].y) / m;
- }
- else
- {
- pcv[cp].x1 = pcv[v1].x;
- }
- pcv[cp++].y1 = WINDOW_TOP;
- }
- if((pcv[v1].y < WINDOW_TOP) && (pcv[v2].y >= WINDOW_TOP))
- {
- // edge is entering display
- if((temp = pcv[v2].x - pcv[v1].x) != 0)
- {
- float m = (float)(pcv[v2].y - pcv[v1].y)/(float)temp;
- pcv[cp].x1 = pcv[v1].x + (WINDOW_TOP - pcv[v1].y) / m;
- }
- else
- {
- pcv[cp].x1 = pcv[v1].x;
- }
- pcv[cp++].y1 = WINDOW_TOP;
- pcv[cp].x1 = pcv[v2].x;
- pcv[cp++].y1 = pcv[v2].y;
- }
- v1 = v2;
- }
- clip->NumOfVertices = cp;
-
- //////////////////////////////////////////////////////////////////
- // clip against lower edge of display
- cp = 0;
-
- // make a pointer to last vertex
- v1 = clip->NumOfVertices - 1;
- for(v2 = 0; v2 < clip->NumOfVertices; v2++)
- {
- // categorize edges by type
- if((pcv[v1].y1 <= WINDOW_BOTTOM) && (pcv[v2].y1 <= WINDOW_BOTTOM))
- {
- // edge is not off bottom of display
- pcv[cp].x = pcv[v2].x1;
- pcv[cp++].y = pcv[v2].y1;
- }
-
- if((pcv[v1].y1 <= WINDOW_BOTTOM) && (pcv[v2].y1 > WINDOW_BOTTOM))
- {
- // edge is leaving display
- if((temp=pcv[v2].x1 - pcv[v1].x1) != 0)
- {
- float m = (float)(pcv[v2].y1 - pcv[v1].y1)/(float)temp;
- pcv[cp].x = pcv[v1].x1 + (WINDOW_BOTTOM - pcv[v1].y1) / m;
- }
- else
- {
- pcv[cp].x = pcv[v1].x1;
- }
- pcv[cp++].y = WINDOW_BOTTOM;
- }
- if((pcv[v1].y1 > WINDOW_BOTTOM) && (pcv[v2].y1 <= WINDOW_BOTTOM))
- {
- // edge is entering display
- if((temp=pcv[v2].x1 - pcv[v1].x1) != 0)
- {
- float m = (float)(pcv[v2].y1 - pcv[v1].y1)/(float)temp;
- pcv[cp].x = pcv[v1].x1 + (WINDOW_BOTTOM - pcv[v1].y1) / m;
- }
- else
- {
- pcv[cp].x = pcv[v1].x1;
- }
- pcv[cp++].y = WINDOW_BOTTOM;
- pcv[cp].x = pcv[v2].x1;
- pcv[cp++].y = pcv[v2].y1;
- }
- v1 = v2;
- }
- clip->NumOfVertices = cp;
- }
-
-
- //--------------------------------------------------------------------------
-
-
- void WaitVerticalRetrace(void)
- {
- asm mov dx,3dah
-
- top_of_retrace:
- asm in al,dx
- asm and al,08h
- asm jnz top_of_retrace
-
- bottom_of_retrace:
- asm in al,dx
- asm and al,08h
- asm jz bottom_of_retrace
- }
-
-
- //-----------------------------------------------------------------------
-
-
- void GetPalette(unsigned char *palettebuffer)
- {
- int i;
-
- for(i=0;i<256;i++)
- {
- outp(0x3c7,i); // color number to get data from
- palettebuffer[i*3] = inp(0x3c9); // red
- palettebuffer[i*3+1] = inp(0x3c9); // green
- palettebuffer[i*3+2] = inp(0x3c9); // blue
- }
- }
-
-
- //-----------------------------------------------------------------------
-
- void SetPalette(unsigned char *palettebuffer)
- {
- int i;
-
- for(i=0;i<256;i++)
- {
- outp(0x3c8,i); // color number to set
- outp(0x3c9,palettebuffer[i*3]); // red
- outp(0x3c9,palettebuffer[i*3+1]); // green
- outp(0x3c9,palettebuffer[i*3+2]); // blue
- }
- }
-
-
- //-----------------------------------------------------------------------
-
-
- void FadeInPalette(unsigned char *palettebuffer,int speed)
- {
- int i,j,k;
- unsigned char temppalette[768]={0};
-
- for(i=0;i<64;i++)
- {
- for(j=0;j<256;j++)
- {
- // do the red component
- if(temppalette[j*3] < palettebuffer[j*3])
- {
- temppalette[j*3]++;
- }
- // do the green component
- if(temppalette[j*3+1] < palettebuffer[j*3+1])
- {
- temppalette[j*3+1]++;
- }
- // do the blue component
- if(temppalette[j*3+2] < palettebuffer[j*3+2])
- {
- temppalette[j*3+2]++;
- }
- }
- for(k=0;k<speed;k++)
- {
- WaitVerticalRetrace();
- }
- SetPalette(temppalette);
- }
- }
-
-
- //-----------------------------------------------------------------------
-
-
- void FadeOutPalette(int speed)
- {
- int i,j,k;
- unsigned char temppalette[768];
-
- GetPalette(temppalette);
-
- for(i=0;i<64;i++)
- {
- for(j=0;j<256;j++)
- {
- // do the red component
- if(temppalette[j*3] > 0)
- {
- temppalette[j*3]--;
- }
- // do the green component
- if(temppalette[j*3+1] > 0)
- {
- temppalette[j*3+1]--;
- }
- // do the blue component
- if(temppalette[j*3+2] > 0)
- {
- temppalette[j*3+2]--;
- }
- }
- for(k=0;k<speed;k++)
- {
- WaitVerticalRetrace();
- }
- SetPalette(temppalette);
- }
- }
-
-
- //-----------------------------------------------------------------------
-
-
- void FadeInOne64th(unsigned char *srcpalette,unsigned char *curpalette)
- {
- int i,j;
-
- for(j=0;j<256;j++)
- {
- // do the red component
- if(curpalette[j*3] < srcpalette[j*3])
- {
- curpalette[j*3]++;
- }
- // do the green component
- if(curpalette[j*3+1] < srcpalette[j*3+1])
- {
- curpalette[j*3+1]++;
- }
- // do the blue component
- if(curpalette[j*3+2] < srcpalette[j*3+2])
- {
- curpalette[j*3+2]++;
- }
- }
- SetPalette(curpalette);
- }
-
-
- //-----------------------------------------------------------------------
-
-
- void FadeOutOne64th(unsigned char *curpalette)
- {
- int i,j;
-
- for(j=0;j<256;j++)
- {
- // do the red component
- if(curpalette[j*3] > 0)
- {
- curpalette[j*3]--;
- }
- // do the green component
- if(curpalette[j*3+1] > 0)
- {
- curpalette[j*3+1]--;
- }
- // do the blue component
- if(curpalette[j*3+2] > 0)
- {
- curpalette[j*3+2]--;
- }
- }
- SetPalette(curpalette);
- }
-
-
- //-----------------------------------------------------------------------
-
-
- void ShowObject(void)
- {
- Rotate_vector_object();
- Rotate_Normals();
- CalculateColor();
- MakePolygonList();
- ZSort();
- if(debug_mode==1)
- {
- x_rect_fill(0,0,319,239,HiddenPageOffs,0);
- }
- DrawPolygonList();
-
- if(debug_mode==1)
- {
- DrawDebugDots();
- x_printf(0,0,HiddenPageOffs,4,"Number of frames = %u",NumOfFrames++);
- x_printf(0,10,HiddenPageOffs,4,"Number of polygons = %i",PolygonList.NumOfPolygons);
- //x_printf(0,20,HiddenPageOffs,4,"Color of polygon 0 = %i",Object.Polygon[0].Color);
- //x_printf(0,40,HiddenPageOffs,4,"Dot Product 0 = %f",dotproduct);
- //x_printf(0,50,HiddenPageOffs,4,"Normal x of polygon 0 = %f",Object.Polygon[0].Normalwx);
- //x_printf(0,60,HiddenPageOffs,4,"Normal y of polygon 0 = %f",Object.Polygon[0].Normalwy);
- //x_printf(0,70,HiddenPageOffs,4,"Normal z of polygon 0 = %f",Object.Polygon[0].Normalwz);
- //x_printf(0,80,HiddenPageOffs,4,"top = %i",EraseBoxOld.top);
- //x_printf(0,90,HiddenPageOffs,4,"bottom = %i",EraseBoxOld.bottom);
- //x_printf(0,100,HiddenPageOffs,4,"left = %i",EraseBoxOld.left);
- //x_printf(0,110,HiddenPageOffs,4,"right = %i",EraseBoxOld.right);
- for(int x=0;x<256;x++)
- {
- x_line(x,229,x,239,x,HiddenPageOffs);
- }
- }
- }
-